<template>
	<div
		v-if="fullWidth"
		class="lexmis-BothScrollArea">
		<ScrollArea
			ref="ScrollArea"
			:delay="delay"
			:visible="vVisible"
			:thumb-style="vThumbStyle"
			:bar-style="vBarStyle"
			v-on="listeners"
			@inner-resize="$_lexmis_innerResize">
			<slot
				:width="outerWidth"
				:height="outerHeight"></slot>
		</ScrollArea>
	</div>
	<div
		v-else-if="fullHeight"
		class="lexmis-BothScrollArea">
		<ScrollArea
			ref="ScrollArea"
			horizontal
			:delay="delay"
			:visible="hVisible"
			:thumb-style="hThumbStyle"
			:bar-style="hBarStyle"
			v-on="listeners"
			@inner-resize="$_lexmis_innerResize">
			<slot
				:width="outerWidth"
				:height="outerHeight"></slot>
		</ScrollArea>
	</div>
	<div
		v-else
		class="lexmis-BothScrollArea"
		@mouseenter="hover=true"
		@mouseleave="hover=false">
		<ScrollArea
			ref="ScrollArea"
			:delay="delay"
			:visible="vVisible"
			:thumb-style="vThumbStyle"
			:bar-style="vBarStyle"
			v-on="listeners">
			<div
				ref="target"
				class="lexmis_scroll">
				<ResizeObserver
					class="lexmis-BothScrollArea_container"
					@resize="$_lexmis_innerResize">
					<slot
						:width="outerWidth"
						:height="outerHeight"></slot>
				</ResizeObserver>
				<QScrollObserver
					horizontal
					:scroll-target="$refs.target"
					debounce="0"
					@scroll="$_lexmis_hscroll"/>
			</div>
		</ScrollArea>
		<div
			class="lexmis_bar"
			:style="hBarStyle"
			:class="barClass"></div>
		<div
			v-touch-pan.horizontal.prevent.mouse.mouseAllDir="$_lexmis_Paning"
			class="lexmis_thumb"
			:style="realThumbStyle"
			:class="thumbClass"></div>
	</div>
</template>

<script>
import {QScrollObserver,TouchPan} from 'quasar';
import ScrollArea from '../scroll-area';
import ResizeObserver from '../resize-observer';
import {gsap} from 'gsap';
import {ScrollToPlugin} from 'gsap/ScrollToPlugin';
gsap.registerPlugin(ScrollToPlugin);
//todo 需要自己实现单项滚动ScrollArea组件, 因为滚动难以同步
/**
 * @author 唐国雄
 * 横纵滚动条区域
 * 属性----------------------
 * :full-width		100%宽度,只有纵向滚动条
 * :full-height		100%高度,只有横向滚动条
 * :v-visible		纵向滚动条显示状态
 * :h-visible		横向滚动条显示状态
 * :delay			滚动条消失延迟
 * :v-Thumb-Style	纵向滚动条样式
 * :v-Bar-Style		纵向滚动槽样式
 * :h-Thumb-Style	横向滚动条样式
 * :h-Bar-Style		横向滚动槽样式
 * 事件----------------------
 * @paning			横向滚动, number
 * @resize			容器大小,{width:number,height:number}
 * @inner-resize	内容大小,{width:number,height:number}
 * @v-scroll		纵向滚动事件,{ref:Component,verticalPosition:number,verticalPercentage:number,verticalSize:number,verticalContainerSize:number}
 * @h-scroll		横向滚动事件,{ref:Component,horizontalPosition:number,horizontalPercentage:number,horizontalSize:number,horizontalContainerSize:number}
 * 插槽----------------------
 * #default		滚动区域的内容,{width:number,height:number}
 * 方法----------------------
 * getVScrollTarget()		获取纵向dom元素
 * getVScrollPosition()		获取纵向滚动距离
 * setVScrollPosition(offset,duration)			设置纵向滚动距离
 * setVScrollPercentage(percentage,duration)	设置纵向滚动百分比
 * getHScrollTarget()		获取横向dom元素
 * getHScrollPosition()		获取横向滚动距离
 * setHScrollPosition(offset,duration)			设置横向滚动距离
 * setHScrollPercentage(percentage,duration)	设置横向滚动百分比
 */
export default {
	name:'BothScrollArea',
	components:{
		ScrollArea,
		ResizeObserver,
		QScrollObserver,
	},
	directives:{
		TouchPan,
	},
	props:{
		//100%宽度,只有纵向滚动条
		fullWidth:Boolean,
		//100%高度,只有横向滚动条
		fullHeight:Boolean,
		//纵向滚动条显示状态
		vVisible:{
			type:Boolean,
			default:null,
		},
		//横向滚动条显示状态
		hVisible:{
			type:Boolean,
			default:null,
		},
		//显示隐藏延时
		delay:{
			type:[String,Number],
			default:1000
		},
		//纵向滚动条样式
		vThumbStyle:Object,
		//纵向滚动槽样式
		vBarStyle:[Array,String,Object],
		//横向滚动条样式
		hThumbStyle:Object,
		//横向滚动槽样式
		hBarStyle:[Array,String,Object],
	},
	data(){
		return {
			//滚动条还未消失
			tempShowing:false,
			//正在滚动滚动条
			panning:false,
			//鼠标是否悬浮
			hover:false,
			//容器宽度
			outerWidth:0,
			//容器高度
			outerHeight:0,
			//实际宽度
			innerWidth:0,
			//滚动条偏移
			scrollLeft:0,
			//放置在ScrollArea组件上的监听器
			listeners:{}
		};
	},
	computed:{
		//滚动条是否隐藏
		thumbHidden(){
			return (
				(this.hVisible===null?this.hover:this.hVisible)!==true&&
				this.tempShowing===false&&
				this.panning===false
			)||this.innerWidth<=this.outerWidth;
		},
		thumbClass(){
			return {
				lexmis_hidden:this.thumbHidden,
			};
		},
		barClass(){
			return {
				lexmis_hidden:this.thumbHidden,
			};
		},
		//滚动条长度
		thumbWidth(){
			const outerWidth=this.outerWidth;
			return Math.min(outerWidth,Math.max(50,Math.floor(outerWidth/this.innerWidth*outerWidth)));
		},
		//滚动条样式
		realThumbStyle(){
			return Object.assign(
				{},
				this.hThumbStyle,
				{
					width:this.thumbWidth+'px',
					left:this.scrollPercentage*(this.outerWidth-this.thumbWidth)+'px',
				}
			);
		},
		//滚动位置百分比
		scrollPercentage(){
			const p=Math.max(0,Math.min(this.scrollLeft/(this.innerWidth-this.outerWidth),1));
			return Math.round(p*10000)/10000;
		},
	},
	created(){
		//纵向滚动监听
		const vScroll=this.$listeners['v-scroll'];
		this.listeners.resize=this.$_lexmis_outerResize;
		if(vScroll){
			this.listeners.scroll=(info) => {
				this.$emit('v-scroll',Object.assign(info,{ref:this}));
			};
		}
		//横向滚动监听防抖
		this.$_lexmis_emitScroll=() => {
			this.$emit('paning',this.scrollLeft);
			if(this.$listeners['h-scroll']!=null){
				const info={ref:this};
				info.horizontalPosition=this.scrollLeft;
				info.horizontalPercentage=this.scrollPercentage;
				info.horizontalSize=this.innerWidth;
				info.horizontalContainerSize=this.outerWidth;
				this.$emit('h-scroll',info);
			}
		};
	},
	activated(){
		if(this.vScrollPosition){
			this.setVScrollPosition(this.vScrollPosition);
		}
		if(this.hScrollPosition){
			this.setHScrollPosition(this.hScrollPosition);
		}
	},
	deactivated(){
		this.vScrollPosition=this.getVScrollPosition();
		this.hScrollPosition=this.getHScrollPosition();
	},
	methods:{
		//横向滚动
		$_lexmis_hscroll(info){
			if(this.scrollLeft!==info.position){
				this.scrollLeft=info.position;
				this.$_lexmis_startTimer();
			}
		},
		//容器大小
		$_lexmis_outerResize(info){
			if(this.outerWidth!==info.width){
				this.outerWidth=info.width;
				this.$_lexmis_startTimer();
			}
			if(this.outerHeight!==info.height){
				this.outerHeight=info.height;
			}
			this.$emit('resize',info);
		},
		//真实宽度
		$_lexmis_innerResize(info){
			if(this.innerWidth!==info.width){
				this.innerWidth=info.width;
				this.$_lexmis_startTimer();
			}
			this.$emit('inner-resize',info);
		},
		//滚动条消失计时
		$_lexmis_startTimer(){
			if(this.tempShowing===true){
				clearTimeout(this.timer);
			}else{
				this.tempShowing=true;
			}
			this.timer=setTimeout(() => {
				this.tempShowing=false;
			},this.delay);
			this.$_lexmis_emitScroll();
		},
		//横向滚动中
		$_lexmis_Paning(e){
			if(e.isFirst===true){
				if(this.thumbHidden===true){
					return;
				}
				this.refPos=this.scrollLeft;
				this.panning=true;
			}else if(this.panning!==true){
				return;
			}
			if(e.isFinal===true){
				this.panning=false;
			}
			const multiplier=(this.innerWidth-this.outerWidth)/(this.outerWidth-this.thumbWidth);
			const scrollLeft=this.refPos+e.offset.x*multiplier;
			this.$refs.target.scrollLeft=scrollLeft;
			// this.$emit('paning',scrollLeft);
		},
		//获取纵向dom元素
		getVScrollTarget(){
			if(!this.fullWidth&&this.fullHeight){
				return null;
			}
			return this.$refs.ScrollArea.getScrollTarget();
		},
		//获取纵向滚动距离
		getVScrollPosition(){
			if(!this.fullWidth&&this.fullHeight){
				return 0;
			}
			return this.$refs.ScrollArea.getScrollPosition();
		},
		//设置纵向滚动距离
		setVScrollPosition(offset,duration){
			if(!this.fullWidth&&this.fullHeight){
				return Promise.resolve();
			}
			return gsap.to(this.$refs.ScrollArea.getScrollTarget(),{
				duration,
				scrollTo:offset,
				overwrite:true,
			}).then(() => undefined);
		},
		//设置纵向滚动百分比
		setVScrollPercentage(percentage,duration){
			const {scrollSize,containerSize}=this.$refs.ScrollArea;
			this.setVScrollPosition(
				percentage*(scrollSize-containerSize),
				duration
			);
		},
		//获取横向dom元素
		getHScrollTarget(){
			if(this.fullWidth){
				return null;
			}
			if(this.fullHeight){
				return this.$refs.ScrollArea.getScrollTarget();
			}
			return this.$refs.target;
		},
		//获取横向滚动距离
		getHScrollPosition(){
			if(this.fullWidth){
				return 0;
			}
			if(this.fullHeight){
				return this.$refs.ScrollArea.getScrollPosition();
			}
			return this.scrollLeft;
		},
		//设置横向滚动距离
		setHScrollPosition(offset,duration){
			if(this.fullWidth){
				return Promise.resolve();
			}
			if(this.fullHeight){
				return gsap.to(this.$refs.ScrollArea.getScrollTarget(),{
					duration,
					scrollTo:{x:offset},
					overwrite:true,
				}).then(() => undefined);
			}
			return gsap.to(this.$refs.target,{
				duration,
				scrollTo:{x:offset},
				overwrite:true,
			}).then(() => undefined);
		},
		//设置横向滚动百分比
		setHScrollPercentage(percentage,duration){
			this.setHScrollPosition(
				percentage*(this.innerWidth-this.outerWidth),
				duration
			);
		},
	}
};
</script>
